<?php
namespace backend\modules\statistics\models;

use backend\models\activeRecords\StatisticsDay;
use backend\models\activeRecords\TPay;
use backend\models\activeRecords\TUser;
use backend\models\activeRecords\TUserLoginLog;
use common\libs\Constants;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;

/**
 * StatisticsDaySearch represents the model behind the search form of `app\models\activeRecords\StatisticsDay`.
 */
class StatisticsDaySearch extends StatisticsDay
{
    public $guild_name;
    public $position;
    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['id', 'reg_num', 'pay_num',  'record_time'], 'integer'],
            [['game_name', 'server_name','position'],'string'],
            [['pay_sum', 'pay_rate', 'arppu', 'next_remains', 'third_remains', 'seven_remains', 'thirty_remains'], 'number'],
            [['guild_sign','guild_name','spread_key_2', 'date'], 'safe'],
        ];
    }

    /**
     * @inheritdoc
     */
    public function scenarios()
    {
        // bypass scenarios() implementation in the parent class
        return Model::scenarios();
    }

    /**
     * Creates data provider instance with search query applied
     *
     * @param array $params
     *
     * @return ActiveDataProvider
     */
    public function search($params)
    {
        $query = StatisticsDay::find();

        // add conditions that should always apply here
        $dataProvider = new ActiveDataProvider([
            'query' => $query,
            'sort' =>[
                'defaultOrder'=>['date'=>'desc']
            ],
        ]);

        $this->load($params);

        if (!$this->validate()) {
            // uncomment the following line if you do not want to return any records when validation fails
            // $query->where('0=1');
            return $dataProvider;
        }

        // grid filtering conditions
        $query->andFilterWhere([
            'id' => $this->id,
            'reg_num' => $this->reg_num,
            'pay_sum' => $this->pay_sum,
            'pay_num' => $this->pay_num,
            'pay_rate' => $this->pay_rate,
            'arppu' => $this->arppu,
            'next_remains' => $this->next_remains,
            'third_remains' => $this->third_remains,
            'seven_remains' => $this->seven_remains,
            'thirty_remains' => $this->thirty_remains,
            'record_time' => $this->record_time,
        ]);

        if(!empty($this->date)){
            $time = explode(' - ',$this->date);
            $query->andFilterWhere(['between','date'
                ,date('Y-m-d',strtotime($time[0]))
                ,date('Y-m-d',strtotime($time[1]))]);
        }

        $query->andFilterWhere(['like', 'game_name', $this->game_name])
            ->andFilterWhere(['like', 'server_name', $this->server_name]);
        $auth = Yii::$app->authManager;
        $roleGuildManager = Constants::ROLE_GUILD_MANAGER;
        $roleGuildChannel = Constants::ROLE_GUILD_CHANNEL;
        if(!empty($auth->getRolesByUser(Yii::$app->user->getId())[$roleGuildManager])){
            $query->andFilterWhere(['like', 'statistics_day.guild_sign', Yii::$app->user->getIdentity()->parent]);
            $query->joinWith('user')
                ->andFilterWhere(['like', 'user.position', $this->position]);
        }elseif(!empty($auth->getRolesByUser(Yii::$app->user->getId())[$roleGuildChannel])){
            $query->joinWith('user')
                ->andFilterWhere(['like', 'user.position', Yii::$app->user->getIdentity()->position]);
        }else{
            $query->joinWith('guild')
                ->andFilterWhere(['like', 'guild.guild_name', $this->guild_name]);
            $query->joinWith('user')
                ->andFilterWhere(['like', 'user.position', $this->position]);
        }
        return $dataProvider;
    }

    public function statisticsDayData()
    {
        set_time_limit(0);
        ignore_user_abort(true);
        $maxRecordTime = empty(StatisticsDay::find()->max('record_time'))?
            0:StatisticsDay::find()->max('record_time');
        $pagePerNumber = 500;
        $userCount = TUser::find()->count();
        for($currentCount = 0;$pagePerNumber * $currentCount<$userCount;$currentCount++){
            $userList = TUser::find()
                ->where('register_time >= :register_time',[':register_time'=>$maxRecordTime])
                ->andWhere('spread_key_1 = :spread_key_1',[':spread_key_1'=>Constants::ANCHOR])
                ->andWhere('reg_game_name <> :reg_game_name',[':reg_game_name'=>'uquq'])
                ->andWhere('length(spread_key)>0')
                ->limit($pagePerNumber)
                ->offset($pagePerNumber * $currentCount)
                ->all();
            $rows = [];
            foreach($userList as $value){
                $rows[] = [
                    'game_name'=>$value->reg_game_name,
                    'guild_sign'=>$value->spread_key,
                    'spread_key_2'=>$value->spread_key_2,
                    'date'=>date('Y-m-d',$value->register_time),
                    'record_time'=>$value->register_time,
                ];
            }
            $command = Yii::$app->db->createCommand()->batchInsert(StatisticsDay::tableName()
                ,['game_name','guild_sign','spread_key_2','date','record_time'],$rows);
            $command->sql = str_replace('INSERT INTO','REPLACE INTO',$command->sql);
            $command->execute();
            $this->recordDayDataByTimeRange($maxRecordTime);
        }

    }

    private function recordDayDataByTimeRange($maxRecordTime)
    {
        $statisticsInfo = StatisticsDay::find()
            ->where('record_time >= :record_time',[':record_time'=>$maxRecordTime])
            ->all();
        $userModel = new TUser();
        $payModel = new TPay();
        foreach($statisticsInfo as $value){
            $startTime = strtotime($value->date." 0:0:0");
            $endTime = strtotime($value->date." 23:59:59");
            $userQuery = $userModel->find()
                ->where('spread_key = :spread_key',[':spread_key'=>$value->guild_sign])
                ->andWhere('spread_key_2 = :spread_key_2',[':spread_key_2'=>$value->spread_key_2])
                ->andWhere('reg_game_name = :reg_game_name',[':reg_game_name'=>$value->game_name])
                ->andFilterWhere(['between','register_time'
                    ,$startTime
                    ,$endTime]);
            $payQuery = $payModel->find()
                ->joinWith('user')
                ->where('t_user.spread_key = :spread_key',[':spread_key'=>$value->guild_sign])
                ->andWhere('t_user.spread_key_2 = :spread_key_2',[':spread_key_2'=>$value->spread_key_2])
                ->andWhere('t_user.reg_game_name = :reg_game_name',[':reg_game_name'=>$value->game_name])
                ->andWhere('pay_state = :pay_state',[':pay_state'=>Constants::Status_Success])
                ->andFilterWhere(['between','pay_time'
                    ,$startTime
                    ,$endTime])
                ->andFilterWhere(['between','t_user.register_time'
                    ,$startTime,$endTime]);
            $value->reg_num = empty($userQuery->count())?0:$userQuery->count();
            $value->pay_sum = empty($payQuery->sum('pay_money'))?0:$payQuery->sum('pay_money');
            $value->pay_num = empty($payQuery->count('distinct pay_game_user'))
                ?0:$payQuery->count('distinct pay_game_user');
            $value->arppu = empty($value->reg_num)?0:$value->pay_sum/$value->reg_num;
            $value->pay_rate = empty($value->reg_num)?0:($value->pay_num/$value->reg_num)*100;
            $value->next_remains = empty($value->reg_num)?0:($this->getRemains($value,$value->date,2)/$value->reg_num)*100;
            $value->third_remains = empty($value->reg_num)?0:($this->getRemains($value,$value->date,3)/$value->reg_num)*100;
            $value->seven_remains = empty($value->reg_num)?0:($this->getRemains($value,$value->date,7)/$value->reg_num)*100;
            $value->thirty_remains = empty($value->reg_num)?0:($this->getRemains($value,$value->date,30)/$value->reg_num)*100;
            $value->save();
        }
    }

    private function getRemains($data,$date,$days){
        $loginLogModel = new TUserLoginLog();
        $startTime = strtotime($date." 0:0:0")+Constants::ONE_DAY*$days;
        $endTime = strtotime($date." 23:59:59")+Constants::ONE_DAY*$days;
        $loginCount = $loginLogModel->find()->joinWith('user')
            ->where('t_user.spread_key = :spread_key',[':spread_key'=>$data->guild_sign])
            ->andWhere('t_user.spread_key_2 = :spread_key_2',[':spread_key_2'=>$data->spread_key_2])
            ->andWhere('t_user.reg_game_name = :reg_game_name',[':reg_game_name'=>$data->game_name])
            ->andFilterWhere(['between','t_user.register_time'
                ,strtotime($date." 0:0:0")
                ,strtotime($date." 23:59:59")])
            ->andFilterWhere(['between','login_time'
                ,$startTime,$endTime])
            ->count('distinct user_id');
        return $loginCount;
    }


}
